/*
    treemodel.cpp

    Provides a simple tree model to show how to create and use hierarchical
    models.
*/

#include <QtGui>
#include <QDir>
#include <QSqlDatabase>
#include <QSqlQuery>

#include "treeitem.h"
#include "treemodel.h"
#include "appmanager.h"


TreeModel::TreeModel( QObject *parent)
    : QAbstractItemModel(parent),
      rootItem(NULL)
{
    clearData();
    mItemCount = 0;
}

TreeModel::~TreeModel()
{
    delete rootItem;
}

int TreeModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
    else
        return rootItem->columnCount();
}

QVariant TreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (role == Qt::SizeHintRole)
      {
        QSize size;
        if (index.parent() == QModelIndex())
          {
            size.setHeight(PARENT_HEIGHT);
          }
        else
          {
            size.setHeight(CHILD_HEIGHT);
          }
        return size;
      }

    if (role != Qt::DisplayRole)
        return QVariant();


    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

    return item->data(index.column());
}

Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;

    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
                               int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return rootItem->data(section);

    return QVariant();
}

QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent)
            const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    TreeItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<TreeItem*>(parent.internalPointer());

    TreeItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QModelIndex TreeModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
    TreeItem *parentItem = childItem->parent();

    if (parentItem == rootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

int TreeModel::rowCount(const QModelIndex &parent) const
{
    TreeItem *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<TreeItem*>(parent.internalPointer());

    return parentItem->childCount();
}

void TreeModel::setupModelData()
{
    this->reset(); // TODO: delete this line
    QSqlDatabase *workDB = appManager->dbWorker()->workDB();

    if (!workDB->isOpen())
    {
        LOG( "TreeModel::setupModelData", "База не була відкрита, отже відкриваємо.", "" );
        workDB->open();
    }

    // query to get all parents
    QSqlQuery query(*workDB);
    bool qres = query.exec(GET_PARENTS_QUERY);
    if (!qres)
    {
        LOG("TreeModel::setupModelData()",
            "Не вдалося завантажити список бітьківських елементів запитом:",
            GET_PARENTS_QUERY);
    }

    QList<TreeItem*> parents;
    parents << rootItem;

    while (query.next()) {
        int styleId = query.value(0).toInt();
        QList<QVariant> tmpList;
        tmpList<<""<<""<<styleId<<"";
        TreeItem *ti = new TreeItem(tmpList, rootItem);
        rootItem->appendChild(ti);
    }
    query.clear();

    // get all childrens for parents
    // TODO: optimize

    int count = 0;

    // cycle for all styles
    int childrenCount = rootItem->childCount();
    for (int styleNum = 0; styleNum < childrenCount; styleNum++)
    {
        TreeItem *styleParent = rootItem->child(styleNum);
        // generate query
        query.prepare(GET_ITEMS_BY_STYLE);
        query.bindValue(":styleId", styleParent->data(2).toString());

        bool qres = query.exec();
        if (qres)
        {
            while (query.next())
            {
                QList<QVariant> tmpList;

                for ( int i=0; i<COL_COUNT; i++ )
                {
                    tmpList<<query.value(i);
                }
                TreeItem *ti = new TreeItem(tmpList, styleParent);
                styleParent->appendChild(ti);
                count++;
            }
        }
        query.clear();
    }
    mItemCount = count;
    LOG( "TreeModel::setupModelData", "Успішно завантажено все дерево платівок.", "" );
}

void TreeModel::refresh()
{
    clearData();
    setupModelData();
//    LOG( "TreeModel::refresh", query().lastQuery(), "" );
    emit needReloadData();
}

void TreeModel::clearData()
{
    if (rootItem!=NULL)
        delete rootItem;

    QList<QVariant> rootData;
    for (int i = 0; i < COL_COUNT; i++)
    {
        rootData << COL_NAMES.at(i);
    }
    rootItem = new TreeItem(rootData);
}

int TreeModel::childCount() const
{
    return mItemCount;
}
